home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / tcoop.arc / TCOOP2.ARC / MSOUNIT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-26  |  11.2 KB  |  387 lines

  1. // msounit.cpp: Menu screen object (mso) class implementation
  2.  
  3. #include "stdio.h"
  4. #include "process.h"
  5. #include "stdlib.h"
  6. #include "string.h"
  7. #include "msounit.h"
  8.  
  9. // -------------------- Meso Methods -----------------------
  10. Meso::Meso(char *N, ActionProc A) 
  11. // Initializes a menu entry object by assigning it a name and 
  12. // action. The object will have no border and will have
  13. // default colors.
  14. // CORRECTION: pg 256, DefColors passed by reference,
  15. //             not by pointer as in book
  16. : Wso(0x00, 0x00, DefColors)
  17. {
  18.   strncpy(Name, N, 39);  Name[39] = 0; // Ensure null termination
  19.   Action = A;
  20.   SetSize(Panel->TextWidth(N), Panel->TextHeight(1));
  21. }
  22.  
  23. void Meso::Draw(void)
  24. // Displays a menu entry 
  25. {
  26.   Wso::Draw();  // Draw the window object 
  27.   Panel->HzWrt(0, 0, Name, Panel->Colors.Wc);
  28. }
  29.  
  30. void Meso::Prompt(void)
  31. // Prompts a menu entry by highlighting it 
  32. {
  33.   Wso::Prompt();  // Select the window
  34.   Panel->Fill(0, 0, Panel->Interior->Wd, Panel->TextHeight(1), 
  35.               ' ', Panel->Colors.Fc);
  36.   Panel->HzWrt(0, 0, Name, Panel->Colors.Fc);
  37. }
  38.  
  39. void Meso::UnPrompt(void)
  40. // Unprompts the menu entry by re-displaying it 
  41. // with its standard attribute 
  42. {
  43.   Panel->Fill(0, 0, Panel->Interior->Wd, Panel->TextHeight(1), 
  44.               ' ', Panel->Colors.Wc);
  45.   Panel->HzWrt(0, 0, Name, Panel->Colors.Wc);
  46.   Wso::UnPrompt(); // De-select window
  47. }
  48.  
  49. void Meso::OnKeyStroke(MsgPkt &M)
  50. // Processes an input key.  The Enter key selects the entry. If
  51. // any other key is pressed the entry's Base (which is the
  52. // menu itself) handles it  
  53. {
  54.   if (M.Code == CrKey) 
  55.      Activate(M); 
  56.      else Base->OnKeyStroke(M); // Send key to base
  57. }
  58.  
  59. void Meso::OnClose(MsgPkt &M)
  60. // Closing a menu entry means to close the menu as well 
  61. {
  62.   Base->SwitchFocus(M);
  63.   M.RtnCode = Close; // Effectively tells the base to close 
  64. }
  65.  
  66. void Meso::Activate(MsgPkt &M)
  67. // Call the menu entry's action. Otherwise, leave the menu
  68. // entry. (Thus, if a MouseUp event occurs outside the menu,
  69. // the entry is de-selected.) 
  70. {
  71.   if (Active) { // The entry must be selected 
  72.      Wso::Activate(M);
  73.      Action(this, M); // Execute the assigned action 
  74.   }
  75.   else {
  76.     Leave(M);         // Leave the menu entry 
  77.   }
  78. }
  79.  
  80. // ----------------------- Meso List Methods ---------------------- 
  81. MesoList::MesoList(void)
  82. // Initializes the list of menu entry objects. The list is 
  83. // implemented as a circular list. 
  84. {
  85.   Last = NULL;   // Indicates the list is empty 
  86. }
  87.  
  88. MesoList::~MesoList(void) 
  89. // This method does nothing because the entries on the list
  90. // also appear on the Iso stack, and will be destroyed when
  91. // the stack is destroyed. 
  92. {
  93.   return;
  94. }
  95.  
  96. void MesoList::Append(Meso *Me)
  97. // Appends a menu entry to the menu list 
  98. {
  99.   if (Last != NULL) {    // List has entries 
  100.      Me->Next = Last->Next;
  101.      Last->Next = Me;    // Add new element 
  102.      Last = Last->Next;  // Update end of list pointer 
  103.   }
  104.   else {                 // List is empty 
  105.      Last = Me;          // Place at top of list 
  106.      Last->Next = Me;
  107.   }
  108. }
  109.  
  110. // ------------ Menu Screen Object Methods ------------- 
  111. Mso::Mso(MesoList *El, int Nc, int Nr, int Sp, int W, int H,
  112.          int Bd, int Fa, ColorPak &Cp)
  113. // Initializes the menu object by creating a window 
  114. // and setting up the menu entries 
  115. : Wso(Bd, Fa, Cp) // Initialize the menu's window
  116. {
  117.   Entries  = El;
  118.   CurrSeln = Entries->Last->Next;
  119.   EntriesDrawn = 0;
  120.   Spacing = Sp;
  121.   SetupDim(Nc, Nr, W, H);  // Sets up the menu dimensions
  122.   Ncols = Nc; Nrows = Nr;  // Store number of columns, rows
  123.   SetSize(W, H);  // Sets the menu width and height 
  124.   SetupEntries(); // Sets the size and attribute for each entry 
  125. }
  126.  
  127. void Mso::SetupDim(int &Nc, int &Nr, int &W, int &H)
  128. // Sets up the menu's dimensions
  129. {
  130.   int SumLen, NumEntries, MaxEntryLen, TxtLen;
  131.   Meso *P;
  132.  
  133.   NumEntries = 0; MaxEntryLen = 0; SumLen = 0;
  134.   P = Entries->Last->Next;
  135.   if (Nr == 1)  { // Horizontal menu 
  136.      do {
  137.        // We use Absc below so coords will not be translated just yet 
  138.        P->SetLocn(SumLen, 0, Absc); 
  139.        SumLen += Panel->TextWidth(P->Name) + Spacing;
  140.        NumEntries++;
  141.        P = P->Next;
  142.      } while (P != Entries->Last->Next);
  143.      SumLen -= Spacing;
  144.      if (SumLen > W) W = SumLen;
  145.      H = Panel->TextHeight(1);
  146.      Nc = NumEntries;
  147.      Nr = 1;
  148.   }
  149.   else if (Nc == 1) { // Vertical menu 
  150.      do {
  151.        // We use Absc below so coords will not be translated just yet 
  152.        P->SetLocn(0, Panel->TextHeight(NumEntries), Absc);
  153.        TxtLen = Panel->TextWidth(P->Name);
  154.        if (TxtLen > MaxEntryLen) MaxEntryLen = TxtLen;
  155.        NumEntries++;
  156.        P = P->Next;
  157.      } while (P != Entries->Last->Next);
  158.      if (MaxEntryLen > W) W = MaxEntryLen;
  159.      H = Panel->TextHeight(NumEntries);
  160.      Nr = NumEntries; Nc = 1;
  161.   }
  162.   else {  // Rectangular menu: 
  163.     printf("Rectangular menus not supported\n");
  164.     exit(1);
  165.   }
  166. }
  167.  
  168. int Mso::EntryWidth(Meso *Me)
  169. // Calculates the width of a menu entry 
  170. {
  171.   if (IsHz())
  172.       return Panel->TextWidth(Me->Name);
  173.       else return Panel->Interior->Wd;
  174. }
  175.  
  176. void Mso::SetupEntries(void)
  177. // Sizes the menu entries and initializes their colors 
  178. {
  179.   Meso *P;
  180.   P = Entries->Last->Next;  // Get the first menu entry 
  181.   do {
  182.     P->Panel->SetSize(EntryWidth(P), Panel->TextHeight(1));
  183.     P->Panel->Colors = Panel->Colors;
  184.     P = P->Next;
  185.   } while (P != Entries->Last->Next);
  186. }
  187.  
  188. void Mso::Open(Iso *B, int X, int Y)
  189. // Open up the menu, open up the menu entries too 
  190. {
  191.   Meso *P;
  192.  
  193.   Wso::Open(B, X, Y);
  194.   P = Entries->Last->Next; // Get the first menu entry 
  195.   do {
  196.     // Display the menu item 
  197.     P->Open(this, P->Panel->Overall->Xul, P->Panel->Overall->Yul);
  198.     P = P->Next;  // Get the next menu entry 
  199.   } while(P != Entries->Last->Next);
  200.   EntriesDrawn = True; // Indicates menu entries are displayed 
  201. }
  202.  
  203.  
  204. void Mso::MoveLoop(MsgPkt &M) 
  205. // Calls the MoveLoop from the parent class to move the menu.
  206. // This feature supports tear-away menus. We return a MouseUp
  207. // event to cause the current menu entry to be selected.  
  208. {
  209.   Wso::MoveLoop(M);
  210.   M.RtnCode = MouseUp; 
  211. }
  212.  
  213. void Mso::Activate(MsgPkt &M) 
  214. // This method handles the case when a MouseUp occurs on 
  215. // the menu's border (see MoveLoop). We wish to switch focus 
  216. // to the current menu entry so that it is highlighted. 
  217. {
  218.   CurrSeln = (Meso *)(SubMgr->Top);
  219.   CurrSeln->SwitchFocus(M);
  220. }
  221.  
  222. void Mso::Leave(MsgPkt &M) 
  223. // Leaves a menu. Before leaving, we must record the
  224. // current menu entry selection. 
  225. {
  226.   CurrSeln = (Meso *)(SubMgr->Top);  // Save current entry
  227.   Wso::Leave(M);                     // Leave the menu
  228. }
  229.  
  230. void Mso::OnKeyStroke(MsgPkt &M)
  231. // Trap and process the arrow keys, otherwise pass the
  232. // key press event to the inherited method. 
  233. {
  234.   switch(M.Code) { // Check for arrow keys
  235.     case UpKey    : if (IsVt()) Back(M); break; // To previous entry 
  236.     case DownKey  : if (IsVt()) Forw(M); break; // To next entry 
  237.     case LeftKey  : if (IsHz()) Back(M); break;
  238.     case RightKey : if (IsHz()) Forw(M); break;
  239.     default:
  240.      Wso::OnKeyStroke(M); // Send other keys to base class
  241.   }
  242. }
  243.  
  244. void Mso::Forw(MsgPkt &M)
  245. // Advances to the next menu entry in the menu object 
  246. {
  247.   CurrSeln = (Meso *)(SubMgr->Top); // Find current selection 
  248.   CurrSeln->Next->SwitchFocus(M);   // Go to next entry 
  249. }
  250.  
  251. void Mso::Back(MsgPkt &M)
  252. // Backs up to the previous menu entry 
  253. {
  254.   Meso *P;
  255.   CurrSeln = (Meso *)(SubMgr->Top); // Find current selection
  256.   P = CurrSeln;
  257.   while (P->Next != CurrSeln) P = P->Next; 
  258.   CurrSeln = P;             // Go to previous entry 
  259.   CurrSeln->SwitchFocus(M); // Select the new entry 
  260. }
  261.  
  262.  
  263. // ----------- Pull-down menu bar methods --------------- 
  264. PullDnBar::PullDnBar(MesoList *Items, int W, int Sp, ColorPak &Cp)
  265. // Initializea a pull-down menu bar object
  266. : Mso(Items, 0, 1, Sp, W,
  267.       Items->Last->Next->Panel->Overall->Ht, 0x00, 0x00, Cp)
  268. {
  269.   SubMso = NULL;
  270. }
  271.  
  272. void PullDnBar::OnKeyStroke(MsgPkt &M)
  273. // First, let the inherited Mso::OnKeyStroke handle the 
  274. // keystroke. If the keystroke is a left or right arrow key, 
  275. // a new entry will be selected by Mso::OnKeyStroke, so
  276. // activate the new menu entry, causing the drop menu to
  277. // drop down. 
  278. {
  279.   Mso::OnKeyStroke(M);
  280.   if ((M.Code == LeftKey) || (M.Code == RightKey)) 
  281.      M.Focus->Activate(M);
  282. }
  283.  
  284. // -------------------- Pull Down Menu ------------------------ 
  285.  
  286. Pmso::Pmso(MesoList *Items, int W, int H, int Sp,
  287.            int Ba, int Fa, ColorPak &Cp)
  288. // Initializes the main pull-down menu screen object 
  289. : Wso(Ba, Fa, Cp)
  290. {
  291.   Bar = new PullDnBar(Items, W, Sp, Cp);
  292.   SetSize(Bar->Panel->Frame->Wd, H);
  293.   Inner = new Wso(0x00, 0x00, Cp);
  294.   Inner->SetSize(Panel->Interior->Wd,
  295.                         Panel->Interior->Ht - 
  296.                         Panel->TextHeight(1));
  297. }
  298.  
  299. void Pmso::Open(Iso *B, int X, int Y)
  300. // Displays the pull-down menu system by opening the main 
  301. // pull-down object on an Iso 
  302. {
  303.   Wso::Open(B, X, Y);
  304.   Bar->Open(this, 0, 0);
  305.   Inner->Open(this, 0, Panel->TextHeight(1));
  306. }
  307.  
  308. // ------------------------------------------------------------------ 
  309. Dmso::Dmso(MesoList *Items, int W, int Ba, int Fa, ColorPak &Cp)
  310. // Initializes a drop menu screen object 
  311. : Mso(Items, 1, 0, 2, W, 0, Ba, Fa, Cp)
  312. {
  313.   Parent = NULL;
  314. }
  315.  
  316. void Dmso::OnClose(MsgPkt &M)
  317. // Closes a drop menu screen object. Note how we must
  318. // set the PullDnBar's SubMso field to NULL, and how we
  319. // must do a typecast. 
  320. {
  321.   ((PullDnBar *)(Parent->Base))->SubMso = NULL; 
  322.   Mso::OnClose(M);
  323. }
  324.  
  325. void Dmso::OnKeyStroke(MsgPkt &M)
  326. // Sends all LeftKey and RightKey events to the pulldown 
  327. // menu, else, let the inherited method (Mso::OnKeyStroke) 
  328. // handle the event. 
  329. {
  330.   if (M.Code == LeftKey || M.Code == RightKey) {
  331.       Parent->Base->OnKeyStroke(M);
  332.   }
  333.   else {
  334.     Mso::OnKeyStroke(M);
  335.   }
  336. }
  337.  
  338. // ------------------------------------------------------------- 
  339.  
  340. void PmesoAction(Wso *Src, MsgPkt &M)
  341. // The action for a pulldown menu entry screen object is
  342. // to switch focus to the last menu entry selected in the
  343. // drop menu. 
  344. {
  345.   ((Pmeso *)(Src))->Vm->CurrSeln->SwitchFocus(M);
  346. }
  347.  
  348. Pmeso::Pmeso(char *N, Dmso *D)
  349. // Initializes a pull-down menu entry screen object 
  350. : Meso(N, PmesoAction)
  351. {
  352.   Vm = D;
  353. }
  354.  
  355. void Pmeso::OnKeyStroke(MsgPkt &M)
  356. // Traps DownKey events so that they cause the sub-menu to drop 
  357. {
  358.   if (M.Code == DownKey) 
  359.      Activate(M); else Meso::OnKeyStroke(M);
  360. }
  361.  
  362. void Pmeso::SwitchFocus(MsgPkt &M)
  363. // Switches focus to Self, erases any drop menu 
  364. // currently displayed, and  draws Self's drop menu 
  365. {
  366.   int Xcoord;
  367.   if (!Active) {
  368.      Meso::SwitchFocus(M); // Must do this first 
  369.      if (((PullDnBar *)(Base))->SubMso != NULL) {
  370.          ((PullDnBar *)(Base))->SubMso->Leave(M);
  371.          ((PullDnBar *)(Base))->SubMso->OnClose(M);
  372.          ((PullDnBar *)(Base))->SubMso = NULL;
  373.      }
  374.      if (Vm != NULL) {     // If there is a drop menu 
  375.         Xcoord = Panel->Overall->Xul - Base->Panel->Overall->Xul;
  376.         if (!Vm->EntriesDrawn) {
  377.            Vm->Open(((Pmso *)(Base->Base))->Inner, Xcoord, 0);
  378.         }
  379.         else Vm->Reopen(Xcoord, 0);
  380.         ((PullDnBar *)Base)->SubMso = Vm;
  381.         Vm->Parent = this;
  382.      } 
  383.   }
  384. }
  385.  
  386.  
  387.